﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace DBD.Common.Map
{
    /// <summary>
    /// 用于模型属性 重命名 的Attribute
    /// </summary>
    [AttributeUsage(AttributeTargets.Property)]
    public class Rename : Attribute
    {
        public readonly string Name;

        public Rename(string name)
        {
            this.Name = name;
        }

    }

    public static class RenameCommon
    {
        /// <summary>
        /// 根据Rename Attribute 处理模型转换
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static T1 Transform<T1, T2>(this T2 model)
        {
            Type type1 = typeof(T1);
            PropertyInfo[] properties1 = type1.GetProperties();

            Type type2 = typeof(T2);
            PropertyInfo[] properties2 = type2.GetProperties();

            Dictionary<string, string> dicRename =
                properties2.ToDictionary(
                    x => x.GetCustomAttributes(true), x => x.Name)
                    .Where(x => x.Key.Count() != 0).ToDictionary(x => ((Rename)x.Key.First()).Name, x => x.Value);

            T1 info = Activator.CreateInstance<T1>();
            foreach (PropertyInfo property1 in properties1)
            {
                //判断是否包含重命名特性
                Rename rename = property1.GetCustomAttributes(true).Select(x => (Rename)x).FirstOrDefault();
                // 包含重命名特性  用rename.Name匹配
                string columnName = rename == null ? property1.Name : rename.Name;

                PropertyInfo property2;
                if (dicRename.ContainsKey(columnName))//已存在key
                    property2 = properties2.FirstOrDefault(x => x.Name == dicRename[columnName]);
                else
                    property2 = properties2.FirstOrDefault(x => x.Name == columnName);

                if (property2 != null)
                    property1.SetValue(info, property2.GetValue(model, null), null);

            }
            return info;
        }

    }
}
